package com.yhos.platform.oopston.core.aop;

import com.yhos.platform.oopston.core.base.Response;
import com.yhos.platform.oopston.core.constant.OperatorConstant;
import com.yhos.platform.oopston.core.exception.BusinessException;
import com.yhos.platform.oopston.core.exception.CustomException;
import com.yhos.platform.oopston.core.utils.DateUtils;
import com.yhos.platform.oopston.core.utils.MessageSourceUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Enumeration;
import java.util.Map;
import java.util.UUID;

@ControllerAdvice(annotations = RestController.class)
public class RestControllerAdvice {

    private Logger logger = LoggerFactory.getLogger(RestControllerAdvice.class);

    @Autowired
    private MessageSourceUtils messageSourceUtils;

    private ParamsThreadLocalManager paramsThreadLocalManager = ParamsThreadLocalManager.getInstance();

    @ExceptionHandler(value = Exception.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public Object errorResponse(HttpServletRequest request, HandlerMethod handlerMethod, Exception ex) {
        String fromSourceId = "";
        ParamsBean params = paramsThreadLocalManager.getParams();
        Map<String, Object> paramValueMap = params != null ? params.getAllRequestParamsMap() : null;
        if (paramValueMap != null) {
            fromSourceId = StringUtils.defaultString(paramValueMap.get(OperatorConstant.FROM_SOURCE_ID) != null ? paramValueMap.get(OperatorConstant.FROM_SOURCE_ID).toString() : null, "");
        }

        try {
            String url = request.getRequestURL().toString();
            String method = request.getMethod();

            logger.info("--------RestControllerAdvice.Request--------"
                    + ".URL." + url + "\n"
                    + ".Method." + method);

            StringBuilder header = new StringBuilder();
            if (request.getHeaderNames() != null) {
                Enumeration<String> headers = request.getHeaderNames();
                while (headers.hasMoreElements()) {
                    String name = headers.nextElement();
                    String value = request.getHeader(name);
                    header = header.append("." + name + ".").append(value).append("\n");
                }
                logger.info("--------RestControllerAdvice.Header--------" + header.toString());
            }
        } catch (Exception e) {

        }

        String success = OperatorConstant.RETURN_FAILURE;
        String errorMessage;
        String errorCode;
        Object val = null;
        if (ex instanceof BusinessException) {
            errorMessage = ex.getMessage();
            errorCode = OperatorConstant.ERROR_CODE_10002;
            logger.info("error message : " + errorMessage, ex);
        } else if (ex instanceof CustomException) {
            errorMessage = ex.getMessage();
            errorCode = ((CustomException) ex).getErrorCode();
            val = ((CustomException) ex).getVal();
            logger.info("error message : " + errorMessage, ex);
        } else {
            errorMessage = ex.getMessage();
            errorCode = OperatorConstant.ERROR_CODE_10001;
            logger.error("error message : " + ex.getMessage(), ex);
        }

        Response response = new Response();
        response.setSuccess(success);
        response.setMsg(errorMessage);
        response.setResponseTime(DateUtils.dateToString(new Date()));
        if (StringUtils.isNotBlank(errorCode)) {
            response.setRet(errorCode);
        }
        if (StringUtils.isBlank(fromSourceId)) {
            fromSourceId = UUID.randomUUID().toString();
        }
        response.setRequestUUID(fromSourceId);
        if(val != null){
            response.setVal(val);
        }
        paramsThreadLocalManager.removeParams();
        return response;
    }

}
